import * as d3 from 'd3'
export class GaugeChart {
  divId = ''
  data = 0
  dataDomain = [0, 50, 100]
  arcMin = -Math.PI / 2
  arcMax = Math.PI / 2
  range = this.arcMax - this.arcMin
  innerRadius = 60
  outerRadius = 80
  labelPad = 10
  arc = d3.arc()
  arcScale = d3.scaleLinear()
  positionX = 0
  positionY = 0
  selection = ''
  gaugeChart = {}

  constructor (divId) {
    this.divId = divId
  }

  draw () {
    this.initChart()
    this.initGauge()
    this.drawDataArc()
  }

  update () {
    this.drawDataArc()
  }

  initChart () {
    this.gaugeChart.padding = {
      left: 20,
      right: 50,
      top: 20,
      bottom: 20
    }
    this.gaugeChart.divHeight = document.getElementById(this.divId).offsetHeight - this.gaugeChart.padding.top - this.gaugeChart
      .padding.bottom
    this.gaugeChart.divWidth = document.getElementById(this.divId).offsetWidth - this.gaugeChart.padding.left - this.gaugeChart
      .padding.right

    this.gaugeChart.svg = d3.select('#' + this.divId).append('svg')
      .attr('width', this.gaugeChart.divWidth + this.gaugeChart.padding.left + this.gaugeChart.padding.right)
      .attr('height', this.gaugeChart.divHeight + this.gaugeChart.padding.top + this.gaugeChart.padding.bottom)
      .attr('class', 'svg_gaugeChart')
  }

  initGauge (selection) {
    if (selection === '' || selection === undefined) {
      this.initChart()
      this.selection = this.gaugeChart.svg
    } else this.selection = selection

    this.arcScale.domain(this.dataDomain).range([this.arcMin, 0, this.arcMax])

    this.arc.innerRadius(this.innerRadius)
      .outerRadius(this.outerRadius)
      .startAngle(this.arcMin)

    let gauge = this.selection.append('g')
      .attr('class', 'gauge')
      .attr('transform', 'translate(' + this.positionX + ',' + this.positionY + ')')

    gauge.append('path')
      .attr('d', this.arc({
        startAngle: this.arcMin,
        endAngle: this.arcMax
      }))
      .style('fill', '#ddd')

    gauge.append('g')
      .attr('class', 'ticks')
      .selectAll('.label')
      .data(this.arcScale.ticks(5))
      .enter()
      .append('text')
      .attr('class', 'tick')
      .attr('x', d => this.outerRadius * Math.sin(this.arcScale(d)))
      .attr('y', d => this.outerRadius * Math.cos(this.arcScale(d)) * -1)
      .attr('dy', '-0.35em')
      .style('font-size', 12)
      .text(String)

    gauge.selectAll('.tick')
      .filter(function (d) {
        return d < 50
      })
      .attr('dx', '-1em')

    gauge.append('g')
      .append('polygon')
      .attr('class', 'point')
      .attr('points', `-2,-10,2,-10,4,0,1,${this.innerRadius * 0.8},-1,${this.innerRadius * 0.8},-4,0`)
      .attr('fill', '#ddd')
      .attr('transform', 'rotate(90)')

    gauge.append('text')
      .attr('class', 'showData')
      .attr('x', -5)
      .attr('y', 20)
      .text(0)

    this.selection.select('.gauge')
      .selectAll('.dataArc')
      .data([{
        startAngle: this.arcMin,
        endAngle: this.arcMin
      }])
      .enter()
      .append('path')
      .attr('class', 'dataArc')
      .attr('d', this.arc)
      .style('fill', '#1a9641')
      .each(function (d) {
        this._current = d
      })
  }

  drawDataArc () {
    let gauge = this.selection.selectAll('.dataArc')

    gauge.data([{
      startAngle: this.arcMin,
      endAngle: this.arcScale(this.data)
    }])
      .transition()
      .duration(1000)
      .attrTween('d', arcTween)

    this.selection.select('.showData').text(this.data)

    this.selection.select('.point')
      .transition()
      .duration(1000)
      .attr('transform', d => {
        let angle = this.arcScale(this.data) - this.arcMin
        return 'rotate(' + (90 + angle / this.range * 180) + ')'
      })
    let arc = this.arc

    function arcTween (a) {
      var i = d3.interpolate(this._current, a)
      this._current = i(0)
      return function (t) {
        return arc(i(t))
      }
    }
  }
}
